import { QXEmitter } from '../../interface';
import { QXEventEmitter } from '../qx-event-emitter/qx-event-emitter';

/**
 * 事件
 *
 * @author chitanda
 * @date 2022-08-30 13:08:53
 * @export
 * @class QXEvent
 * @template T
 */
export class QXEvent<T extends QXEmitter<T>> {
  /**
   * 事件初始化
   *
   * @private
   * @type {QXEventEmitter}
   * @memberof QXEvent
   */
  private e: QXEventEmitter;

  /**
   * Creates an instance of QXEvent.
   * @param {number} [maxListeners] 最大单个事件监听个数
   * @memberof QXEvent
   */
  constructor(maxListeners?: number) {
    this.e = new QXEventEmitter();
    // 设置最大监控事件数量
    this.e.setMaxListeners(maxListeners || 300);
  }

  /**
   * 获取指定事件当前监听个数
   *
   * @author chitanda
   * @date 2022-10-26 19:10:39
   * @template K
   * @param {K} name
   * @return {*}  {number}
   */
  getSize<K extends keyof T>(name: K): number {
    return this.e.getSize(name as string);
  }

  /**
   * 订阅事件
   *
   * @author chitanda
   * @date 2022-08-21 18:08:31
   * @template K
   * @param {K} name
   * @param {(...args: Parameters<T[K]>) => ReturnType<T[K]>} cb
   */
  on<K extends keyof T>(
    name: K,
    cb: (...args: Parameters<T[K]>) => ReturnType<T[K]>,
  ): void {
    this.e.addListener(name as string, cb);
  }

  /**
   * 取消订阅事件
   *
   * @author chitanda
   * @date 2022-08-21 18:08:46
   * @template K
   * @param {K} name
   * @param {(...args: Parameters<T[K]>) => ReturnType<T[K]>} cb
   */
  off<K extends keyof T>(
    name: K,
    cb: (...args: Parameters<T[K]>) => ReturnType<T[K]>,
  ): void {
    this.e.removeListener(name as string, cb);
  }

  /**
   * 发送事件
   *
   * @template K
   * @param {K} name
   * @param {T[K]} [arg]
   * @memberof QXEvent
   */
  emit<K extends keyof T>(name: K, ...args: Parameters<T[K]>): void {
    this.e.emit(name as string, ...args);
  }

  /**
   * 发送事件，并等待所有监听器执行完毕
   *
   * @author chitanda
   * @date 2022-08-21 18:08:30
   * @template K
   * @param {K} name
   * @param {...Parameters<T[K]>} args
   * @return {*}  {(Promise<Awaited<ReturnType<T[K]>>[]>)}
   */
  asyncEmit<K extends keyof T>(
    name: K,
    ...args: Parameters<T[K]>
  ): Promise<Awaited<ReturnType<T[K]>>[]> {
    return this.e.asyncEmit(name as string, ...args);
  }

  /**
   * 释放所有事件监听
   *
   * @author chitanda
   * @date 2022-08-30 17:08:09
   */
  reset(): void {
    this.e.reset();
  }
}
